<template>
  <div>
    <h3>进度条文件上传</h3>
    <div class="upload_div">
      <div class="upload_button_box">
        <input
          ref="fileInput"
          type="file"
          class="upload_input"
          @change="changeFile"
        />
        <button
          class="upload_button select"
          @click="chooseFile"
          :class="[{ disabled: disabledStyle }]"
        >
          选择文件
        </button>
        <button
          class="upload_button upload"
          @click="uploadFile"
          :class="[{ loading: loadingStyle }]"
        ></button>
      </div>
      <div class="upload_tip" v-if="uploadTipVisible">
        可以上传任何类型的文件，大小不能超过2G
      </div>
      <div
        class="upload_list"
        v-if="uploadListVisible"
        @click="removeSelectedFile"
      >
        <div v-for="(file, index) in files" :key="index">
          文件：{{ file.name }}
          <el-button type="text" size="small"><span>移除</span></el-button>
        </div>
      </div>
      <div class="upload_progress" v-if="uploadProgressVisible">
        <div ref="progress" class="value"></div>
      </div>
    </div>
  </div>
</template>

<script>
import { uploadSingleFile } from "@/api/upload/ProgressSingleUploader.js";
export default {
  data() {
    return {
      uploadTipVisible: true,
      uploadListVisible: false,
      uploadProgressVisible: false,
      disabledStyle: false,
      loadingStyle: false,
      files: [],
    };
  },
  methods: {
    chooseFile() {
      this.$refs.fileInput.click();
    },
    changeFile(event) {
      // 为了确保是单一文件上传，所以每次选择新文件时，都清空files数组
      this.files.length = 0;

      const file = event.srcElement.files[0];
      if (!file) return;

      this.setUploadListVisiable(true);

      this.files.push({
        name: file.name,
        file: file,
      });
    },
    removeSelectedFile(event) {
      const target = event.target;
      if (target.tagName === "SPAN") {
        this.setUploadListVisiable(false);
        this.files.length = 0;
      }
    },
    async uploadFile() {
      // 如果没有选择文件，则提示先选择文件
      if (this.files.length == 0) {
        this.$message({
          type: "info",
          message: "请先选择文件",
        });
        return;
      }

      // 如果已经选择文件，则判断文件是否符合要求
      const file = this.files[0].file;
      let shouldUpload = true;
      if (this.onBeforeUpload) {
        shouldUpload = this.onBeforeUpload(file);
      }
      if (!shouldUpload) {
        this.$message({
          type: "warning",
          message: "文件不符合要求",
        });
        return;
      }

      try {
        // 如果文件符合要求，则利用formData上传文件
        const formData = new FormData();
        formData.append("file", file);

        // 上传文件开始，让上传按钮不可用
        this.setUploadInProgress(true);

        // 第二个参数是监听上传进度的回调函数
        let resultVo = await uploadSingleFile(formData, (event) => {
          let { loaded, total } = event;
          this.$refs.progress.style.width = `${(loaded / total) * 100}%`;
        });
        if (resultVo.code == 200) {
          this.$refs.progress.style.width = "100%";
          this.$message({
            type: "success",
            message: "文件上传成功：" + resultVo.data,
          });
          return;
        }
        throw resultVo.msg;
      } catch (err) {
        this.$message({
          type: "error",
          message: err,
        });
      } finally {
        this.setUploadInProgress(false);
        this.setUploadListVisiable(false);
      }
    },
    setUploadInProgress(val) {
      this.disabledStyle = val;
      this.loadingStyle = val;
      this.uploadProgressVisible = val;
    },
    setUploadListVisiable(visiable) {
      this.uploadTipVisible = !visiable;
      this.uploadListVisible = visiable;
    },
  },
};
</script>

<style scoped>
.upload_div {
  margin: auto;
  width: 400px;
  height: 150px;
  border: #ccc dashed 1px;
}
.upload_input {
  display: none;
}
.upload_button {
  margin: 5px;
  padding: 5px;
  border-radius: 5px;
  border: #ccc outset 1px;
}
.upload_button:active {
  border: #ccc solid 1px;
}
.select {
  background-color: #66cef6;
}
.upload {
  background-color: #cce708;
}
.upload::after {
  content: "上传到服务器";
}
.upload_tip {
  font-size: 12px;
}
.upload_list {
  font-size: 12px;
}
.upload_progress {
  border-radius: 5px;
  height: 5px;
  width: 100%;
  background-color: #ccc;
}
.upload_progress .value {
  height: 100%;
  width: 0%;
  background-color: #8ab42e;
  transition: width .3s;
}
.disabled {
  pointer-events: none;
  background-color: #ccc;
}
.loading {
  width: 23px;
  height: 23px;
  border: 5px solid #ccc;
  border-bottom-color: #ff3d00;
  border-radius: 50%;
  display: inline-block;
  background: #fff;
  animation: rotation 0.7s linear infinite;
  pointer-events: none;
}
.loading::after {
  content: "";
}

@keyframes rotation {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>